// $Id: interface_impl.hpp 2 2009-09-02 08:47:42Z joseph2002 $
/*
 * Copyright 2009 Joseph Wu
 * Distributed under the Boost Software License, Version 1.0.
 * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
 *
 * For more information, see http://xpcomplus.sourceforge.net
 */

#ifndef XPCOM_IMPL_INTERFACE_IMPL_HPP
#define XPCOM_IMPL_INTERFACE_IMPL_HPP

#include <xpcom/config.hpp>
#include <boost/mpl/placeholders.hpp>
#include <boost/mpl/transform.hpp>
#include <xpcom/interface.hpp>

#ifdef BOOST_HAS_ABI_HEADERS
#include BOOST_ABI_PREFIX
#endif

namespace xpcom {
namespace impl {

//
// An interface implementation skeleton, which provides more convenience methods
// for user to implement the interface.
// By default, interface_impl inherits from T, so it can be used as the
// original type.
//
// This class is used by object implementation.
//
template <typename Class, typename T, typename Base = T>
class XPCOM_NO_VTABLE interface_impl : public Base
{
public:
    typedef T type;
    typedef Base impl_type;
};

//
// Specialized interface_impl for root interface.
// Every interface_impl specialization should inherit from this one, directly
// or indirectly.
//
template <typename Class, typename Base>
class XPCOM_NO_VTABLE interface_impl<Class, interface, Base> : public Base
{
public:
    typedef interface type;
    typedef Base impl_type;

protected:
    // Access the class pointer
    XPCOM_FORCEINLINE
    Class* _object()
    {
        return static_cast<Class*>(this);
    }
};

//
// Meta function to retrieve implementation type for interface.
//
template <typename Class, typename T, typename Base = T>
struct interface_impl_type
{
    typedef typename interface_impl<Class, T, Base>::impl_type type;
};

//
// Meta function to convert each type in the sequence to its interface
// implementation type.
//
template <typename Class, typename Seq>
struct interface_impl_sequence
{
    typedef typename boost::mpl::transform<
        Seq, interface_impl_type<Class, boost::mpl::_1>
    >::type type;
};

} // namespace xpcom::impl
} // namespace xpcom

//
// Access control of raw method of interface implementations.
// Private by default.
//
#if defined(XPCOM_ENABLE_PUBLIC_RAW_METHOD_ACCESS)
#  ifdef XPCOM_IMPL_RAW_METHOD_ACCESS
#    undef XPCOM_IMPL_RAW_METHOD_ACCESS
#  endif
#  define XPCOM_IMPL_RAW_METHOD_ACCESS public
#elif defined(XPCOM_ENABLE_PROTECTED_RAW_METHOD_ACCESS)
#  ifdef XPCOM_IMPL_RAW_METHOD_ACCESS
#    undef XPCOM_IMPL_RAW_METHOD_ACCESS
#  endif
#  define XPCOM_IMPL_RAW_METHOD_ACCESS protected
#endif

#ifndef XPCOM_IMPL_RAW_METHOD_ACCESS
#  define XPCOM_IMPL_RAW_METHOD_ACCESS private
#endif

#ifdef BOOST_HAS_ABI_HEADERS
#include BOOST_ABI_SUFFIX
#endif

#endif // XPCOM_IMPL_INTERFACE_IMPL_HPP
